﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;

namespace Surveillance
{
    public class Enemy 
    {
        #region Robot declarations
        private const float MOVEMENT_SPEED = 0.2f;
        private Texture2D enemyTexture;
        private Vector2 worldPosition;
        private Vector2 initialPosition;
        private Rectangle targetRectangle;
        private List<Vector2> wayPoints;
        private List<Vector2> InitialWayPoints;
        private int currentWayPointIndex;
        private GraphicsDevice graphicDevice;

        #endregion

        #region Enemy constructors

        public Enemy(ContentManager content, Vector2 position, int width, int height, GraphicsDevice graphic, List<Vector2> points)
        {
            enemyTexture = content.Load<Texture2D>(@"Textures\enemy");
            worldPosition = position;
            initialPosition = position;
            targetRectangle = new Rectangle((int)position.X, (int)position.Y, width, height);
            graphicDevice = graphic;
            wayPoints = points;
            InitialWayPoints = points;
            currentWayPointIndex = 0;
        }

        #endregion

        #region Enemy update and draw

        public void Update(GameTime gameTime, List<Wall> wallList, List<Door> doorList, List<Elevator> elevatorList, List<PressurePlate> plateList)
        {
            if (notOnGround(gameTime, wallList, elevatorList))
            {
                applyGravity(gameTime);
            }
            else
            {
                moveToNextWaypoint(gameTime, wallList, doorList);
                checkIfOnPlates(plateList);
            }
        }

        private void moveToNextWaypoint(GameTime gameTime, List<Wall> wallList, List<Door> doorList)
        {
            float elapsed = gameTime.ElapsedGameTime.Milliseconds;
            if (Math.Abs(worldPosition.X - wayPoints.ElementAt<Vector2>(currentWayPointIndex).X) <= 2)
            {
                //got to waypoint
                currentWayPointIndex++;
                if (currentWayPointIndex >= wayPoints.Count)
                {
                    currentWayPointIndex = 0;
                }
            }
            else
            {
                //not at waypoint, decide to which to direction to move
                if (wayPoints.ElementAt<Vector2>(currentWayPointIndex).X > worldPosition.X)
                {
                    //needs to move right
                    if (canMoveRight(wallList, doorList))
                    {
                        worldPosition.X += elapsed * MOVEMENT_SPEED;
                    }
                }
                else if (wayPoints.ElementAt<Vector2>(currentWayPointIndex).X < worldPosition.X)
                {
                    //needs to move left
                    if (canMoveLeft(wallList, doorList))
                    {
                        worldPosition.X -= elapsed * MOVEMENT_SPEED;
                    }
                }
                targetRectangle.X = (int)worldPosition.X;
            }
        }

        private bool notOnGround(GameTime gameTime, List<Wall> wallList, List<Elevator> elevatorList)
        {
            foreach (Elevator elevator in elevatorList)
            {
                if (elevator.TargetLocation.Intersects(targetRectangle) && elevator.TargetLocation.Y > targetRectangle.Y)
                {
                    worldPosition.Y = elevator.TargetLocation.Y - 29;
                    targetRectangle.Y = (int)worldPosition.Y;
                    return false;
                }
            }
            foreach (Wall wall in wallList)
            {
                if (wall.TargetRectangle.Intersects(targetRectangle) && wall.TargetRectangle.Y > targetRectangle.Y)
                {
                    return false;
                }
            }
            return true;
        }

        private void applyGravity(GameTime gameTime)
        {
            float elapsed = gameTime.ElapsedGameTime.Milliseconds;
            worldPosition.Y += Game1.GRAVITY * elapsed;
            targetRectangle.Y = (int)worldPosition.Y;
        }


        private bool canMoveRight(List<Wall> wallList, List<Door> doorList)
        {
            foreach (Wall wall in wallList)
            {
                if (wall.TargetRectangle.Intersects(targetRectangle) && wall.WorldPosition.X > worldPosition.X && wall.TargetRectangle.Y < targetRectangle.Y)
                {
                    return false;
                }
            }
            foreach (Door door in doorList)
            {
                if (door.TargetLocation.Intersects(targetRectangle) && door.TargetLocation.X > worldPosition.X && door.TargetLocation.Y < targetRectangle.Y && !door.IsOpen)
                {
                    return false;
                }
            }
            return true;
        }

        private bool canMoveLeft(List<Wall> wallList, List<Door> doorList)
        {
            foreach (Wall wall in wallList)
            {
                if (wall.TargetRectangle.Intersects(targetRectangle) && wall.WorldPosition.X < worldPosition.X && wall.TargetRectangle.Y < targetRectangle.Y)
                {
                    return false;
                }
            }
            foreach (Door door in doorList)
            {
                if (door.TargetLocation.Intersects(targetRectangle) && door.TargetLocation.X < worldPosition.X && door.TargetLocation.Y < targetRectangle.Y && !door.IsOpen)
                {
                    return false;
                }
            }
            return true;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(enemyTexture, targetRectangle, Color.White);
        }

        private void checkIfOnPlates(List<PressurePlate> plateList)
        {
            foreach (PressurePlate plate in plateList)
            {
                if (plate.TargetRectangle.Intersects(targetRectangle))
                {
                    plate.stepOn();
                }
            }
        }

        #endregion

       

        #region enemy reset

        public void reset()
        {
            worldPosition = initialPosition;
            targetRectangle.X = (int)initialPosition.X;
            targetRectangle.Y = (int)initialPosition.Y;
            currentWayPointIndex = 0;
            wayPoints = InitialWayPoints;
        }

        #endregion

        #region Enemy properties

        public Rectangle TargetRectangle
        {
            get { return targetRectangle; }
            set { targetRectangle = value; }
        }

        public List<Vector2> WayPoints
        {
            get { return wayPoints; }
            set { wayPoints = value; }
        }

        #endregion
    }
}

